﻿using System;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using cludg.Infrastructure.Core;
using cludg.Services.Environment;

namespace cludg.Services.Images
{
	using Repository.Images;

	public class ImageService : IImageService
	{
		// TODO: читать из config
		protected static IDictionary<ImageSize, int> RealSizes =
			new Dictionary<ImageSize, int>
			{
				{ ImageSize.SmallAvatar, 48 },
				{ ImageSize.Avatar, 240 },
				{ ImageSize.ImageSubject, 480 }
			};

		protected readonly IImageRepository Repository;

		protected readonly ISettingService SettingService;

		public ImageService(IImageRepository repository, ISettingService settingService)
		{
			Repository = repository;
			SettingService = settingService;
		}

		private Image CreateThumbnailImage(Image image, ImageSize size)
		{
			if (size == ImageSize.Real)
			{
				var imageClone = image.Clone() as Image;
				return imageClone;
			}

			int w;
			int h;
			if (image.Width > image.Height)
			{
				w = RealSizes[size];
				h = image.Height * w / image.Width;
			}
			else
			{
				h = RealSizes[size];
				w = image.Width * h / image.Height;
			}

			if ((w > image.Width) || (h > image.Height))
			{
				var imageClone = image.Clone() as Image;
				return imageClone;
			}

			var bitmap = new Bitmap(w, h, PixelFormat.Format24bppRgb);
			bitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);

			using (var graphics = Graphics.FromImage(bitmap))
			{
				graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

				graphics.DrawImage(image,
								   new Rectangle(0, 0, w, h),
								   new Rectangle(0, 0, image.Width, image.Height),
								   GraphicsUnit.Pixel);
			}

			return bitmap;
		}

		private void AddWatermark(Image image)
		{
			var watermarkImageId = SettingService[Const.SettingWatermarkImage] as string;
			if (!string.IsNullOrWhiteSpace(watermarkImageId))
			{
				using (var watermarkImage = Image.FromStream(Repository.GetStream(watermarkImageId)))
				{
					using (var graphics = Graphics.FromImage(image))
					{
						graphics.DrawImage(watermarkImage, image.Width - watermarkImage.Width,
						                   image.Height - watermarkImage.Height);
					}
				}
			}
			else
			{
				throw new ApplicationException(string.Format("Не задана настройка Watermark изображения '{0}'",
					                                            Const.SettingWatermarkImage));
			}
		}

		public string[] Add(Stream stream, ImageSize[] sizes, bool addWatermark = false)
		{
			var ids = new string[sizes.Length];
			using (var img = Image.FromStream(stream))
			{
				var idIndex = 0;
				foreach (var size in sizes)
				{
					string id;
					using (var thumbnail = CreateThumbnailImage(img, size))
					{
						using (var thumbnailStream = new MemoryStream())
						{
							// NOTE: Это как то работает =)
							var bmp = new Bitmap(new Bitmap(thumbnail));
							if (addWatermark)
							{
								AddWatermark(bmp);
							}

							bmp.Save(thumbnailStream, ImageFormat.Png);
							thumbnailStream.Position = 0;

							id = Repository.Add("png", thumbnailStream);
						}
					}
					ids[idIndex] = id;
					idIndex++;
				}
			}
			return ids;
		}

		public string GetUrl(string imageId)
		{
			return Repository.GetUrl(imageId);
		}

		public void Delete(string id)
		{
			Repository.Delete(id);
		}
	}
}
